//
//  ResponseData+Rx.swift
//  MT
//
//  Created by zhang qiang on 2018/11/21.
//  Copyright © 2018年 张强. All rights reserved.

import Foundation

import Moya
import RxSwift
import ObjectMapper

enum ResponseDataError {
    case ParseError
}

extension ResponseDataError: Swift.Error { }


public extension Response {
    
    
    /// 映射到一个原始的数据类型
    ///
    /// - Parameter type: 原始数据 类型
    /// - Returns: 转化后的数据
    /// - Throws: 出现的错误
    func mapResponseOriginalData<T>(type:T.Type) throws -> ResponseOriginalData<T>? {
        do {
            
            let jsonObj =  try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            
            let object = Mapper<ResponseOriginalData<T>>().map(JSONObject: jsonObj)
            
            return object
            
            
        } catch {
            throw ResponseDataError.ParseError
        }
    }
    
    /// 映射到一个遵循BaseMappable的数据对象
    ///
    /// - Parameter type: 原始数据 类型
    /// - Returns: 转化后的数据
    /// - Throws: 出现的错误
    func mapResponseObjectData<T : Mappable>(type:T.Type) throws -> ResponseObjectData <T>? {
        do {
            
            let jsonObj =  try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            
            let object = Mapper<ResponseObjectData<T>>().map(JSONObject: jsonObj)
            
            return object
            
        } catch {
            throw ResponseDataError.ParseError
        }
    }
    
    /// 映射到一个原始的数据类型
    ///
    /// - Parameter type: 原始数据 类型
    /// - Returns: 转化后的数据
    /// - Throws: 出现的错误
    func mapResponseArrayData<T : Mappable>(type:T.Type) throws -> ResponseArrayData<T>? {
        do {
            
            let jsonObj =  try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            
            let object = Mapper<ResponseArrayData<T>>().map(JSONObject: jsonObj)
            
            return object
            
        } catch {
            throw ResponseDataError.ParseError
        }
    }

}

public extension ObservableType where E == Response {
    
    func mapResponseOriginalData<T>(type:T.Type) -> Observable<ResponseOriginalData<T>?> {
        return flatMap { response -> Observable<ResponseOriginalData<T>?> in
            return Observable.just(try response.mapResponseOriginalData(type: T.self))
        }
    }
    
    func mapResponseObjectData<T>(type:T.Type) -> Observable<ResponseObjectData<T>?> {
        return flatMap { response -> Observable<ResponseObjectData<T>?> in
            return Observable.just(try response.mapResponseObjectData(type: T.self))
        }
    }
    
    func mapResponseArrayData<T>(type:T.Type) -> Observable<ResponseArrayData<T>?> {
        return flatMap { response -> Observable<ResponseArrayData<T>?> in
            return Observable.just(try response.mapResponseArrayData(type: T.self))
        }
    }
    
    
}


public extension PrimitiveSequence where TraitType == SingleTrait, ElementType == Response{
    
    func mapResponseOriginalData<T>(type: T.Type) -> Single<ResponseOriginalData<T>?> {
        return flatMap { response -> Single<ResponseOriginalData<T>?> in
            return Single.just(try response.mapResponseOriginalData(type: T.self))
        }
    }
    
    func mapResponseObjectData<T : Mappable>(type: T.Type) -> Single<ResponseObjectData<T>?> {
        return flatMap { response -> Single<ResponseObjectData<T>?> in
            return Single.just(try response.mapResponseObjectData(type: T.self))
        }
    }
    
    func mapResponseArrayData<T : Mappable>(type: T.Type) -> Single<ResponseArrayData<T>?> {
        return flatMap { response -> Single<ResponseArrayData<T>?> in
            return Single.just(try response.mapResponseArrayData(type: T.self))
        }
    }
    
    
}

